单页应用 路由系统 与 链接跳转、页面渲染 三者之间的最佳实践

发布于 · 最后修改时间

随着 Google Chrome 的升级改进,Polymer 上使用的接口接近稳定,所以我就将 Polymer 拿出来进行重新学习。
学习 Polymer 和其它框架不一样的是,其它框架,遇到问题,只能是阅读源码或者寻求社区帮助。Polymer 遇到问题,最重要的想法就是:这是原生的接口,用原生开发的思想去解决。那么问题往往就迎刃而解了。

这篇文章涉及到的是如标题所示的路由系统 与 链接跳转、页面渲染三者之间的关系。

以往的开发思维就是:绑定就是一切!大部分 MV*框架过来的人包括我的思维都有一个定视流程:链接的改变 → 触发路由改变 → 触发改变状态机 → 触发渲染页面上要显示那部分的内容。
这是一个很正确的流程,这种绑定是稳定的,就等于即便是触发链条上某一个节点,后面的节点也能正确的触发渲染。

然而这里有一个很重要的问题需要去重视:渲染性能。

就因为这是一条因果链,所以我们惯性思维往往就是使用统一的数据源来进行管理。这也导致了我跑到Polymer/paper-tabs下头发了一个相关的提问: (https://github.com/PolymerElements/paper-tabs/issues/182)。

但后来我从原生的角度去进行思考后,想到了问题所在,这不是框架或者组件的问题,而是思维方式的问题。纠正后,我现在的思维方式是这样的:

首先:链接、链接选择器(列表菜单、tabs 等带选择的组件) 这类的组件数据绑定归为一起。确保页面上的元素的联动关系不变:比如在窄屏有一个竖向的导航,宽屏有一个横向导航,二者的数据绑定是要一致的。

image
image

当用户点击链接后,我们要做的就是将 loading 效果打开。而此时的内容部分标题不改发生改变。如果是旧思维的单数据源绑定关系链的话,标题肯定会跟变,内容部分也会进入不友好的空白状态(或者会带一个 loading 提示)。
但我们遵从原生的特性的话:比如用户在浏览器地址栏中键入另外一个地址,页面不会马上发生改变,而是依旧显示当前页面状态,并显示一个 loading 的信号。因为你可能会进行取消操作,那么当前页面依旧会友好地为用户服务。
同理,在用户点击链接后,我们要做的仅仅是把 loading 效果打开就行了。效果如如下

image

当页面数据加载下来,紧接的就是页面切换动画了(PS:要注意的是用户可能在加载期间点击了其它链接,所以我们要在每次加载前的时候生成一个 render_id,并在加载完成后进行渲染前对比这个 render_id 是否匹配。以免错误地渲染)。在页面完成切换后,那么这时候就用户就可以确认他已经切换到他想要的页面了。

在视觉上认可后,由于这时候动画已经执行完毕,我们可以对路由进行改变了,
最后路由的改变单向影响到链接选择器组件上。

image

综上所属:路由与链接选择器的关系是单向绑定的关系,这点很重要,如果加载出错了,那么链接选择器应该回滚选择,回滚到什么状态,应该问路由,然后再去显示错误的信息。

很常见的双向绑定的结果就是,当加载出错,处理函数获取 404 的内容并显示,那么链接选择器切换到 404 选项,而双向绑定把这个结果反映到路由上,这是错误的!因为当用户发现错误进行刷新页面的时候,由于链接变成了 404,那么他怎么刷新都是 404,所以切记使用 路由 → 链接选择器 这样的单向绑定。


最后一张图总结:

image

参考源码:
https://gist.github.com/Gaubee/b3f1cb93b7fb593fd3d00a834ffd8332